package com.git.hui.yinshua.biz.user.service;

import com.git.hui.yinshua.api.model.ExceptionUtil;
import com.git.hui.yinshua.api.model.ListRsp;
import com.git.hui.yinshua.api.model.ReqInfoContext;
import com.git.hui.yinshua.api.model.Status;
import com.git.hui.yinshua.api.model.permission.UserRole;
import com.git.hui.yinshua.biz.common.wx.WxUserHelper;
import com.git.hui.yinshua.biz.rest.models.user.req.UserAddReq;
import com.git.hui.yinshua.biz.rest.models.user.req.UserSearchReq;
import com.git.hui.yinshua.biz.rest.models.user.req.UserUpdateReq;
import com.git.hui.yinshua.biz.rest.models.user.res.UserInfoAddrDto;
import com.git.hui.yinshua.biz.rest.models.user.res.UserInfoDto;
import com.git.hui.yinshua.biz.rest.models.user.res.UserLoginDto;
import com.git.hui.yinshua.biz.user.dao.domain.UserAddressEntity;
import com.git.hui.yinshua.biz.user.dao.domain.UserEntity;
import com.git.hui.yinshua.biz.user.dao.repository.UserAddressRepository;
import com.git.hui.yinshua.biz.user.dao.repository.UserRepository;
import com.git.hui.yinshua.biz.user.service.convert.UserConvert;
import com.git.hui.yinshua.biz.user.service.helper.UserPwdEncoder;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 用户服务
 *
 * @author YiHui
 * @date 2024/6/11
 */
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserAddressRepository userAddressRepository;
    @Autowired
    private WxUserHelper wxHelper;
    @Autowired
    private UserSessionService userSessionService;
    @Autowired
    private UserPwdEncoder userPwdEncoder;

    /**
     * 微信登录
     *
     * @param code
     * @return
     */
    public UserLoginDto wxLogin(String code) {
        ImmutablePair<String, String> wxId = wxHelper.getWxId(code);
        UserEntity user = userRepository.queryOrInitByWxId(wxId.left, wxId.right);
        UserInfoDto dto = UserConvert.toUser(user);
        UserLoginDto vo = new UserLoginDto();
        vo.setUser(dto);
        vo.setToken(userSessionService.saveSession(dto));
        return vo;
    }

    /**
     * 添加用户
     *
     * @param addReq
     * @return
     */
    public UserInfoDto createUser(UserAddReq addReq) {
        UserEntity user = userRepository.queryByUname(addReq.getUname());
        if (user != null) {
            // 用户名重复
            throw ExceptionUtil.of(Status.StatusEnum.USER_EXISTS, addReq.getUname());
        }

        user = new UserEntity();
        user.setUname(addReq.getUname());
        user.setPassword(userPwdEncoder.encPwd(addReq.getPwd()));
        user.setNickname(addReq.getNickName());
        user.setAvatar(addReq.getImg());
        user.setSource("后台");
        UserRole role = UserRole.roleOf(addReq.getRole());
        user.setRole(role.getRole());
        userRepository.save(user);
        return UserConvert.toUser(user);
    }

    /**
     * 账号密码登录
     *
     * @param uname
     * @param pwd
     * @return
     */
    public UserLoginDto pwdLogin(String uname, String pwd) {
        UserEntity user = userRepository.queryByUname(uname);
        if (user == null) {
            throw ExceptionUtil.of(Status.StatusEnum.USER_NOT_EXISTS, uname);
        }

        if (!userPwdEncoder.match(pwd, user.getPassword())) {
            throw ExceptionUtil.of(Status.StatusEnum.USER_PWD_ERROR);
        }

        UserInfoDto dto = UserConvert.toUser(user);
        UserLoginDto vo = new UserLoginDto();
        vo.setUser(dto);
        vo.setToken(userSessionService.saveSession(dto));
        return vo;
    }

    /**
     * 推出登录
     *
     * @return
     */
    public boolean logout() {
        userSessionService.removeSession(ReqInfoContext.getReqInfo().getSessionId());
        return true;
    }

    /**
     * 获取用户信息
     *
     * @param userId
     * @return
     */
    public UserInfoDto getUserInfo(Integer userId) {
        UserEntity user = userRepository.queryById(userId);
        return UserConvert.toUser(user);
    }

    /**
     * 用户密码更新
     *
     * @param uname  登陆用户名
     * @param oldPwd 旧密码
     * @param newPwd 新密码
     * @return
     */
    public UserInfoDto updatePwd(String uname, String oldPwd, String newPwd) {
        UserEntity user = userRepository.queryByUname(uname);
        if (!Objects.equals(user.getId(), ReqInfoContext.getReqInfo().getUserId())
                || !userPwdEncoder.match(oldPwd, user.getPassword())) {
            throw ExceptionUtil.of(Status.StatusEnum.USER_PWD_ERROR);
        }

        user.setPassword(userPwdEncoder.encPwd(newPwd));
        userRepository.update(user);
        return UserConvert.toUser(user);
    }

    public UserInfoDto updateUser(UserUpdateReq req) {
        UserEntity user = userRepository.queryById(req.getUid());
        if (!UserRole.superAdmin(ReqInfoContext.getReqInfo().getUser().getRole())) {
            // 非超管时
            if (UserRole.superAdmin(user.getRole())) {
                // 1. 非超管，不能更新其他超管的信息
                throw ExceptionUtil.of(Status.StatusEnum.FORBID_ERROR);
            }

            if (req.getRole() != null && UserRole.superAdmin(req.getRole())) {
                // 2. 非超管，不能添加超管用户
                throw ExceptionUtil.of(Status.StatusEnum.FORBID_ERROR);
            }
        }

        if (req.getRole() != null) {
            user.setRole(req.getRole());
        }

        if (!StringUtils.isBlank(req.getImg())) {
            user.setAvatar(req.getImg());
        }
        if (!StringUtils.isBlank(req.getPhone())) {
            user.setPhone(req.getPhone());
        }
        if (!StringUtils.isBlank(req.getNickName())) {
            user.setNickname(req.getNickName());
        }
        if (!StringUtils.isBlank(req.getPwd())) {
            user.setPassword(userPwdEncoder.encPwd(req.getPwd()));
        }
        userRepository.update(user);
        return UserConvert.toUser(user);
    }

    /**
     * 更新图片
     *
     * @param userId
     * @param avatar
     * @return
     */
    public UserInfoDto updateUserInfo(Integer userId, String avatar, String nickName, String phone) {
        UserEntity user = userRepository.updateUser(userId, nickName, phone, avatar);
        UserInfoDto dto = UserConvert.toUser(user);
        userSessionService.updateSessionVal(ReqInfoContext.getReqInfo().getSessionId(), dto);
        return dto;
    }

    /**
     * 用户列表查询
     *
     * @param search
     * @return
     */
    public ListRsp<UserInfoAddrDto> listUser(UserSearchReq search) {
        // 1.查询用户列表
        List<UserEntity> list = userRepository.list(search);
        if (CollectionUtils.isEmpty(list)) {
            return ListRsp.newRsp(Collections.emptyList(), search.getPage(), search.getSize());
        }

        // 2.查询用户总数
        int cnt = userRepository.count(search);

        // 3.补充用户地址
        List<Integer> userIdList = list.stream().map(UserEntity::getId).collect(Collectors.toList());
        Map<Integer, List<UserAddressEntity>> addressMap = userAddressRepository.batchQueryUserAddressList(userIdList);

        // 4.结果封装
        List<UserInfoAddrDto> res = new ArrayList<>(list.size());
        list.forEach(user -> {
            UserInfoAddrDto addrDto = new UserInfoAddrDto();
            addrDto.setUser(UserConvert.toUser(user));
            List<UserAddressEntity> addrList = addressMap.get(user.getId());
            addrDto.setAddress(UserConvert.batchToAddress(addrList));
            res.add(addrDto);
        });
        ListRsp<UserInfoAddrDto> ans = ListRsp.newRsp(res, search.getPage(), search.getSize());
        ans.setTotal(cnt);
        return ans;
    }

    public List<UserInfoDto> listUserByUserIds(Collection<Integer> users) {
        List<UserEntity> list = userRepository.listByIds(users);
        return UserConvert.batchToUser(list);
    }
}
